﻿using System;
using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using Habanero.Base;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using Habanero.BO.Loaders;
using Habanero.Smooth;
using NUnit.Framework;

namespace Firestarter.Test.Base.BusinessObjectMerger
{
    [TestFixture]
    public class TestMergeableBORegistry
    {
        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
        }

        [SetUp]
        public virtual void SetupTest()
        {

        }

        [Test]
        public void Test_Register_WithType_ShouldRegister()
        {
            //---------------Set up test pack-------------------
            var mergeableBORegistry = new MergeableBORegistry();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            mergeableBORegistry.Register<MockBo, MergeBO<MockBo>>();
            //---------------Test Result -----------------------
            Assert.IsTrue(mergeableBORegistry.Contains<MockBo>());
        }
        [Test]
        public void Test_RegisterTwice_WithType_ShouldRegisterSecondType()
        {
            //---------------Set up test pack-------------------
            var mergeableBORegistry = new MergeableBORegistry();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            mergeableBORegistry.Register<MockBo, MergeBO<MockBo>>();
            mergeableBORegistry.Register<MockBo, MergeBOStub>();
            //---------------Test Result -----------------------
            Assert.IsTrue(mergeableBORegistry.Contains<MockBo>());
            Assert.IsInstanceOf<MergeBOStub>(mergeableBORegistry.Resolve<MockBo>());
        }
        [Test]
        public void Test_Resolve_ForGenericType_WhenRegistered_ShouldResolveRegisteredType()
        {
            //---------------Set up test pack-------------------
            var mergeableBORegistry = new MergeableBORegistry();
            mergeableBORegistry.Register<MockBo, MergeBOStub>();
            //---------------Assert Precondition----------------
            Assert.IsTrue(mergeableBORegistry.Contains<MockBo>());
            //---------------Execute Test ----------------------
            var mergeBO = mergeableBORegistry.Resolve<MockBo>();
            //---------------Test Result -----------------------
            Assert.IsNotNull(mergeBO);
            Assert.IsInstanceOf<MergeBOStub>(mergeBO);
        }
        [Test]
        public void Test_Resolve_ForGeneicType_WhenNotRegistered_ShouldCreateSubType()
        {
            //---------------Set up test pack-------------------
            var mergeableBORegistry = new MergeableBORegistry();
            //---------------Assert Precondition----------------
            Assert.IsFalse(mergeableBORegistry.Contains<MockBo>());
            //---------------Execute Test ----------------------
            var mergeBO = mergeableBORegistry.Resolve<MockBo>();
            //---------------Test Result -----------------------
            Assert.IsNotNull(mergeBO);
           // Assert.IsInstanceOf<MockBo>(mergeBO);
            Assert.IsInstanceOf<MergeBO<MockBo>>(mergeBO);
        }
        [Test]
        public void Test_Resolve_ForType_WhenNotRegistered_ShouldCreateSubType()
        {
            //---------------Set up test pack-------------------
            var mergeableBORegistry = new MergeableBORegistry();
            //---------------Assert Precondition----------------
            Assert.IsFalse(mergeableBORegistry.Contains<MockBo>());
            //---------------Execute Test ----------------------
            var mergeBO = mergeableBORegistry.Resolve(typeof(MockBo));
            //---------------Test Result -----------------------
            Assert.IsNotNull(mergeBO);
         //   Assert.IsInstanceOf<MergeBOStub>(mergeBO);
            Assert.IsInstanceOf<MergeBO<MockBo>>(mergeBO);
        }

        [Test]
        public void Test_Instance_ShouldReturnInstance()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            var mergeableBORegistry = MergeableBORegistry.Instance;
            //---------------Test Result -----------------------
            Assert.IsNotNull(mergeableBORegistry);
        }

    }
    public class MockBo2 : BusinessObject, IMergableBo
    {
        public string TestStringProp
        {
            get { return (string)GetPropertyValue("TestStringProp"); }
            set { SetPropertyValue("TestStringProp", value); }
        }

        public override string ToString()
        {
            return TestStringProp;
        }

        public ChangeType PendingChangeType { get; set; }

        public bool PendingChangeApproved { get; set; }
    }
    public class MockBo : BusinessObject, IMergableBo
    {

        public class InnerMockBo : MockBo
        {
            public new static ClassDef CreateClassDef()
            {
                return CreateClassDefWithProp<string>();
            }

            public new static ClassDef CreateClassDefWithProp<TPropType>()
            {
                return CreateMyClassDef<TPropType>(typeof(InnerMockBo));
            }
        }

        public static ClassDef CreateClassDef()
        {
            return CreateClassDefWithProp<string>();
        }

        public static ClassDef CreateClassDefWithProp<TPropType>()
        {
            return CreateMyClassDef<TPropType>(typeof(MockBo));
        }

        private static ClassDef CreateMyClassDef<TPropType>(Type classType)
        {
            PropDefCol propDefCol = new PropDefCol();
            PrimaryKeyDef primaryKeyDef = new PrimaryKeyDef();
            ClassDef classDef = new ClassDef(classType, primaryKeyDef,
                                             propDefCol, new KeyDefCol(), new RelationshipDefCol());
            PropDef idProp = new PropDef("IdProp", typeof(Guid), PropReadWriteRule.ReadWrite, null);
            propDefCol.Add(idProp);
            primaryKeyDef.Add(idProp);
            propDefCol.Add(new PropDef("TestProp", typeof(TPropType), PropReadWriteRule.ReadWrite, null));
            return classDef;

        }
        [AutoMapPrimaryKey]
        public Guid IdProp
        {
            get { return (Guid)GetPropertyValue("IdProp"); }
            set { SetPropertyValue("IdProp", value); }
        }

        public object TestProp
        {
            get { return GetPropertyValue("TestProp"); }
            set { SetPropertyValue("TestProp", value); }
        }
        public string TestStringProp
        {
            get { return (string)GetPropertyValue("TestStringProp"); }
            set { SetPropertyValue("TestStringProp", value); }
        }

        public ChangeType PendingChangeType { get; set; }

        public bool PendingChangeApproved { get; set; }
    }
}